# utils/parameter_space.py
from typing import List, Dict, Any, Iterator, Tuple
import itertools


class ParameterGrid:
    """
    定义并迭代参数网格。
    """

    def __init__(self, param_dict: Dict[str, List[Any]]):
        """
        :param param_dict: 一个字典，键是参数名，值是该参数的候选值列表。
                           例如: {"ema_short": [10, 12, 15], "ema_long": [20, 25, 30]}
        """
        if not param_dict:
            raise ValueError("参数字典不能为空。")
        for param_name, values in param_dict.items():
            if not isinstance(values, list) or not values:
                raise ValueError(f"参数 '{param_name}' 的值必须是非空列表。")

        self.param_dict = param_dict
        self.param_names = sorted(param_dict.keys())  # 确保迭代顺序一致

    def __iter__(self) -> Iterator[Dict[str, Any]]:
        """
        迭代所有可能的参数组合。
        返回一个字典，键是参数名，值是该组合下的参数值。
        """
        value_lists = [self.param_dict[name] for name in self.param_names]
        for combination_values in itertools.product(*value_lists):
            yield dict(zip(self.param_names, combination_values))

    def __len__(self) -> int:
        """返回参数组合的总数。"""
        count = 1
        for values in self.param_dict.values():
            count *= len(values)
        return count


# 示例用法:
if __name__ == '__main__':
    params_to_tune = {
        "ema_period_5m": [10, 12],
        "rsi_period_5m": [7, 8],
        "rsi_lower_threshold": [65, 70]
    }
    grid = ParameterGrid(params_to_tune)
    print(f"总共参数组合数量: {len(grid)}")
    for i, param_set in enumerate(grid):
        print(f"组合 {i + 1}: {param_set}")